import { DownOutlined, UpOutlined } from '@ant-design/icons';
import { Field } from '@formily/core';
import { DroppableWidget, getMessage, TextWidget } from '@inbiz/react';
import { SizeType } from 'antd/lib/config-provider/SizeContext';
import { Button, Form, Input, message, Modal } from 'antd';
import React, {
  ReactChild,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import FullModal from '../FullModal';
import { InBizTableCtx, InBizTableRefCtx, TableCtx } from '../../context';
import formatters from '../../formatters';
import { useColumnConfig, useIsDesigner } from '../../hooks';
import { EventsMap, objIsNotEmpty, SearchConst } from '../../shared';
import tableApi from './serviceApi';
import { ExclamationCircleFilled } from '@ant-design/icons';
import '../../style.less'

const positionMap = {
  center: 'center',
  left: 'flex-start',
  right: 'flex-end',
};

const QueryBtn = (props: {
  children?: ReactChild;
  style: { height: string };
  setStyle: (
    value: React.SetStateAction<{
      height: string;
    }>,
  ) => void;
}) => {
  const { style, children, setStyle } = props;
  const oneRowHeight = '53px';
  const oneHundredPercent = '100%';
  const [form] = Form.useForm();
  const { searchRef, tableTopRef } = useContext(InBizTableRefCtx);
  const { tableCacheRef, fetchTagData } = useContext(TableCtx);
  const { queryFields } = useColumnConfig();
  const isDesignable = useIsDesigner();
  const {
    searchButtonPosition = SearchConst.right,
    searchButtonSize = SearchConst.expanded,
    emit,
    inbiz,
    controlId,
    expandedButton,
    saveSearch,
  } = useContext(InBizTableCtx);
  const buttonStyle = {
    justifyContent: positionMap[searchButtonPosition],
  };
  const [visible, setVisible] = useState(false);
  const getSearchValues = (isSaveSearch = false) => {
    const values = {};
    (inbiz as any)?.getFields?.(controlId)?.forEach((field: Field) => {
      if (field.hasOwnProperty('value') && field?.componentProps?.tablequeryfield) {
        // 成员选择查询时需要格式化查询数据
        values[field?.componentProps?.tablequeryfield] = {
          value: formatters.formatConditionValue(field),
          type: field?.componentType,
          name: field.props.name,
        };
      }
    });
    const initParams = searchRef.current.initParams;
    const searchValues =
      objIsNotEmpty(values) && queryFields
        ? formatters.getQueryGroups(queryFields, values, initParams)
        : [];
    if (!isSaveSearch) {
      searchRef.current = {
        ...searchRef.current,
        pageInfo: {
          ...searchRef.current.pageInfo!,
          current: 1,
        },
        conditions: searchValues,
        iConditions: {
          ...searchRef.current.iConditions,
          pageIndex: 1
        }
      };
    }
    return searchValues;
  };
  const onSaveSearch = useCallback(() => {
    (inbiz as any)?.validate?.(controlId)?.then(() => {
      const data = getSearchValues(true);
      const selectTagName = tableTopRef.current?.selectTag;
      const isNull = data.every((item) => !item.condition.length);
      if (isNull) {
        message.error(getMessage('Table.tips.saveFailed'));
        return;
      }
      if (selectTagName && selectTagName != '') {
        Modal.confirm({
          className: 'inbiz-table-save-search-modal',
          title: `${getMessage('Table.isSave')}"${selectTagName}"${getMessage(
            'Table.condition',
          )}`,
          content: getMessage('Table.saveCoverCondition'),
          icon: <ExclamationCircleFilled />,
          okText: getMessage('Table.sure'),
          cancelText: getMessage('Table.cancel'),
          onOk() {
            const data = getSearchValues(true);
            let tags = tableTopRef.current?.data || {};
            const index = tags[controlId].findIndex((item) => item.name == selectTagName);
            if (index != -1) {
              tags[controlId][index].data = data;
            }
            const configValue = JSON.stringify({ ...tags });
            tableApi.saveTableSearch(inbiz, configValue).then((res) => {
              fetchTagData && fetchTagData();
            });
          },
        });
      } else {
        setVisible(true);
      }
    });
  }, [tableTopRef.current]);
  const onReset = useCallback(() => {
    (inbiz?.reset as any)?.(controlId);
    getSearchValues();
    searchRef.current = {
      ...searchRef.current,
      isQueryClick: false
    }
    tableTopRef.current?.setSelectTag?.(null);
    tableCacheRef.current?.refresh?.();
  }, []);
  const onSearch = useCallback(() => {
    (inbiz as any)
      ?.validate?.(controlId)
      ?.then(() => {
        getSearchValues();
        tableCacheRef.current?.refresh?.();
      })
      .catch((err: any) => console.log('search-valid', err));
  }, []);
  const onExpanded = () => {
    if (isDesignable) {
      return;
    }
    (emit as any)?.(
      EventsMap.onClick,
      style.height === oneHundredPercent ? SearchConst.collapse : SearchConst.expanded,
    );
    if (style.height === oneRowHeight) {
      return setStyle({ height: oneHundredPercent });
    }
    setStyle({ height: oneRowHeight });
  };

  const onCancel = useCallback(() => {
    form.resetFields();
    setVisible(false);
  }, []);

  const onOk = useCallback(() => {
    form.validateFields().then((values) => {
      const data = getSearchValues(true);
      const tags = tableTopRef.current?.data || {};
      const configValue = JSON.stringify({
        ...tags,
        [controlId]: [...(tags?.[controlId] || []), { name: values.name?.trim(), data }],
      });
      tableApi
        .saveTableSearch(inbiz, configValue)
        .then((res) => {
          message.success(getMessage('Table.tips.saveSuccess'));
          form.resetFields();
          fetchTagData && fetchTagData();
          setVisible(false);
        })
        .catch((err) => {
          console.log('save-search', err);
        });
    });
  }, []);
  const nameValidatorRules = useCallback(
    (rule, value, callback) => {
      const tags = tableTopRef.current?.data || {};
      const tagNames = tags?.[controlId]?.map((tag: { name: string }) => tag.name) || [];
      const isHas = tagNames.some((tag: string) => value && tag === value.trim());
      if (!value || value.trim() == '') {
        return Promise.reject(new Error(getMessage('Table.tips.noName')));
      } else if (isHas) {
        return Promise.reject(new Error(getMessage('Table.tips.repeatName')));
      }
      return Promise.resolve();
    },
    [tableTopRef?.current],
  );
  const renderModalContent = useMemo(() => {
    return (
      <div>
        <Form form={form} labelAlign="left">
          <Form.Item
            name="name"
            label={getMessage('Table.tagName')}
            rules={[
              {
                required: true,
                validator: nameValidatorRules,
              },
            ]}
          >
            <Input allowClear />
          </Form.Item>
        </Form>
      </div>
    );
  }, []);

  useEffect(() => {
    tableTopRef.current = {
      ...tableTopRef.current,
      onReset,
    };
  }, []);

  return children ? (
    <>
      <div className={'button-box'} style={buttonStyle}>
        {saveSearch && (
          <Button
            onClick={() => {
              (emit as any)?.(EventsMap.onClick, 'saveSearch');
              (emit as any)?.(EventsMap.onSaveSearch);
              onSaveSearch();
            }}
            size={searchButtonSize as SizeType}
          >
            <TextWidget>Table.button.saveSearchCondition</TextWidget>
          </Button>
        )}
        <Button
          onClick={() => {
            (emit as any)?.(EventsMap.onClick, 'reset');
            (emit as any)?.(EventsMap.onClearClick);
            onReset();
          }}
          size={searchButtonSize as SizeType}
        >
          <TextWidget>Table.button.repossess</TextWidget>
        </Button>
        <Button
          onClick={() => {
            (emit as any)?.(EventsMap.onClick, 'search');
            (emit as any)?.(EventsMap.onQueryClick, 'search');
            onSearch();
          }}
          size={searchButtonSize as SizeType}
          type="primary"
        >
          <TextWidget>Table.inquire</TextWidget>
        </Button>
        {expandedButton === 'visible' && (
          <Button
            type={'text'}
            onClick={onExpanded}
            size={searchButtonSize as SizeType}
            className="expanded"
          >
            {style.height === oneHundredPercent ? (
              <>
                <TextWidget>Table.button.putAway</TextWidget>
                <UpOutlined />
              </>
            ) : (
              <>
                <TextWidget>Table.button.expand</TextWidget>
                <DownOutlined />
              </>
            )}
          </Button>
        )}
      </div>
      <FullModal
        className="inbiz-save-search-modal"
        title={getMessage('Table.button.saveSearchCondition')}
        width={400}
        okText={getMessage('Table.sure')}
        visible={visible}
        centered={true}
        onOk={onOk}
        forceRender={true}
        onCancel={onCancel}
        render={renderModalContent}
      />
    </>
  ) : null;
};

const TableTopQuery = (props: any) => {
  const isDesignable = useIsDesigner();
  const oneRowHeight = '53px';
  const oneHundredPercent = '100%';
  const { searchExpanded = SearchConst.expanded } = useContext(InBizTableCtx);
  const countRef = useRef<boolean>(false);
  const initStyle = () => {
    if (searchExpanded === SearchConst.collapse) {
      return { height: oneRowHeight };
    }
    return {
      height: oneHundredPercent,
    };
  };
  const [style, setStyle] = useState<{ height: string }>(initStyle());
  useEffect(() => {
    //设计器模式下拖拽组件，自动展开
    if (!countRef.current) {
      countRef.current = true;
      return;
    }
    if (isDesignable)
      setStyle((oldStyle) => {
        if (style.height === oneRowHeight) {
          return { height: oneHundredPercent };
        }
        return oldStyle;
      });
  }, [props.children]);
  return isDesignable ? (
    <div {...props}>
      <DroppableWidget
        style={{
          width: '100%',
          ...props['style'],
        }}
        height={'100%'}
      >
        <div>{props.children}</div>
      </DroppableWidget>
      <QueryBtn {...props} />
    </div>
  ) : (
    <>
      <div style={style} className="search-items">
        {props.children}
      </div>
      {props.children && <QueryBtn {...props} style={style} setStyle={setStyle} />}
    </>
  );
};

export default TableTopQuery;

